﻿// Copyright (c) Inossem. All rights reserved.
// Licensed under the LGPL-3.0 license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace DWF.Studio.RemoteCtrls
{
    /// <summary>
    /// 活动探测器
    /// </summary>
    [Serializable]
    public class TypeProber
    {
        private string[] _assemblyResolutionPaths = null;

        public TypeProber(string[] searchPaths)
        {
            _assemblyResolutionPaths = searchPaths;
        }

        /// <summary>
        /// 探测
        /// </summary>
        /// <param name="searchPaths"></param>
        /// <returns></returns>
        public string[] ProbeActivities()
        {
            AppDomain domain = AppDomain.CreateDomain("DWF.Studio.ActivityProbe"); //创建程序域
            domain.AssemblyResolve += appDomain_AssemblyResolve;

            Type type = typeof(TypeProberProxy);
            var prober = (TypeProberProxy)domain.CreateInstanceFromAndUnwrap(type.Assembly.Location, type.FullName); //封送
            var activities = prober.ProbeActivities(_assemblyResolutionPaths); //探测
            prober.Dispose();

            domain.AssemblyResolve -= appDomain_AssemblyResolve;
            AppDomain.Unload(domain);//卸载域

            return activities.ToArray();
        }

        public async Task<string[]> ProbeActivitiesAsync()
        {
            string[] activities = null;
            await Task.Run(() =>
            {
                activities = ProbeActivities();
            });

            return activities;
        }

        public string[] ProbeAssemblies()
        {
            AppDomain domain = AppDomain.CreateDomain("DWF.Studio.AssemblyProbe"); //创建程序域
            domain.AssemblyResolve += appDomain_AssemblyResolve;

            Type type = typeof(TypeProberProxy);
            var prober = (TypeProberProxy)domain.CreateInstanceFromAndUnwrap(type.Assembly.Location, type.FullName); //封送
            var assemblies = prober.ProbeAssemblies(_assemblyResolutionPaths); //探测
            prober.Dispose();

            domain.AssemblyResolve -= appDomain_AssemblyResolve;
            AppDomain.Unload(domain);//卸载域

            return assemblies.ToArray();
        }

        public async Task<string[]> ProbeAssembliesAsync()
        {
            string[] assemblies = null;
            await Task.Run(() =>
            {
                assemblies = ProbeAssemblies();
            });

            return assemblies;
        }

        private Assembly appDomain_AssemblyResolve(object sender, ResolveEventArgs args)
        {
            Assembly[] loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies();
            foreach (Assembly asm in loadedAssemblies)
            {
                if (asm.FullName.Equals(args.Name))
                    return asm;
            }

            AssemblyName asmInfo = new AssemblyName(args.Name);
            for (int i = 0; i < this._assemblyResolutionPaths.Length; i++)
            {
                string asmFilePath = Path.Combine(this._assemblyResolutionPaths[i], asmInfo.Name + ".dll");
                if (File.Exists(asmFilePath))
                    return Assembly.LoadFrom(asmFilePath);
                else
                {
                    asmFilePath = Path.Combine(this._assemblyResolutionPaths[i], asmInfo.Name + ".exe");
                    if (File.Exists(asmFilePath))
                        return Assembly.LoadFrom(asmFilePath);
                }
            }

            return null;
        }
    }
}
